package CtrLayer;

import java.util.ArrayList;
import java.util.Date;

import DataLayer.DB.DBDelOrdre;
import DataLayer.DB.DBEkstraService;
import DataLayer.Model.DelOrdre;
import DataLayer.Model.EkstraService;
import DataLayer.Model.Ordre;
import DataLayer.Model.Ordre.OrdreStatus;
import DataLayer.Model.Service;

/**
 * PaintingCtr can create new and update already existing orders with both services and
 * extraservices, it also creates the extraservices.
 * 
 * @author Gruppe 4 - Dennis Biil, Brian Smed, Kristian Henriksen og Anders Engbo
 * @version 1.0
 */
public class PaintingCtr implements IFPaintingCtr
{
	private Ordre ordre;
	private ArrayList<DelOrdre> deleteList;
	private ArrayList<EkstraService> deleteEkstraList;
	private int runningId; // This id will be negative to enable using "dummy"
	private static PaintingCtr instance = null;

	private PaintingCtr()
	{
		ordre = new Ordre();
	}

	public static PaintingCtr getInstance()
	{
		if (instance == null)
		{
			instance = new PaintingCtr();
		}
		return instance;
	}

	@Override
	public void startPaintingOrdre()
	{
		ordre = new Ordre(
				new Date().getTime(), new Date().getTime(), OrdreStatus.CREATED,
				"Painting", false, 0, 0, 0, "", null, new ArrayList<DelOrdre>());
		deleteList = new ArrayList<DelOrdre>();
		deleteEkstraList = new ArrayList<EkstraService>();
		resetRunningId();
		ordre.setOrdreId(-1);
	}

	@Override
	public void setPaintingOrdre(int ordreId)
	{
		OrdreCtr oCtr = new OrdreCtr();
		ordre = oCtr.getOrdre(ordreId);
	}

	public void setPaintingOrdreKunde(int kundeId)
	{
		OrdreCtr oCtr = new OrdreCtr();
		ordre.setKunde(oCtr.getKunde(kundeId));
	}

	@Override
	public ArrayList<Service> getAllService(boolean synlig)
	{
		ServiceCtr sCtr = new ServiceCtr();
		return sCtr.getAllServicer(synlig);
	}

	@Override
	public ArrayList<DelOrdre> getAllDelOrdre()
	{
		return ordre.getDelOrdre();
	}

	@Override
	public void addService(int antal, Service s)
	{
		DelOrdre delo = new DelOrdre(antal, null, s, new ArrayList<EkstraService>());
		delo.setDelordreId(useRunningId());
		ordre.getDelOrdre().add(delo);
	}

	public void addEkstraService(int delOrdreId, String beskrivelse, double pris) throws Exception
	{
		int i = getDelOrdreIndex(delOrdreId);
		EkstraService es = new EkstraService(beskrivelse, pris);
		es.setEkstraServiceId(useRunningId());
		ordre.getDelOrdre().get(i).addEkstraService(es);
	}

	@Override
	public DelOrdre getDelOrdre(int delOrdreId)
	{
		DelOrdre tmpDelOrdre = null;
		if (delOrdreId < 0)
		{
			int i = 0;
			boolean found = false;
			while (!found && i < ordre.getDelOrdre().size())
			{
				DelOrdre delo = ordre.getDelOrdre().get(i);
				if (delo.getDelordreId() == delOrdreId)
				{
					tmpDelOrdre = delo;
					found = true;
				}
				else
				{
					i++;
				}
			} // end while
		}
		else
		{
			OrdreCtr oCtr = new OrdreCtr();
			tmpDelOrdre = oCtr.getDelOrdre(delOrdreId);
		}
		return tmpDelOrdre;
	}

	@Override
	public void updateServiceAntal(int delOrdreId, int antal, int ServiceId)
	{
		ServiceCtr sCtr = new ServiceCtr();
		Service s = sCtr.getService(ServiceId);
		DelOrdre delo = getDelOrdre(delOrdreId);
		int index = ordre.getDelOrdre().indexOf(delo);
		delo.setAntal(antal);
		delo.setService(s);
		ordre.getDelOrdre().set(index, delo);
	}

	// removes a service from the order, if an ekstraservice is attached to the Service, deletes
	// those too.
	@Override
	public void removeServiceOrEkstra(int delOrdreId, String standard)
	{
		DelOrdre delo = getDelOrdre(delOrdreId);
		int i = getDelOrdreIndex(delOrdreId);
		if (ordre.getDelOrdre().get(i).getService().getMalestandard().equals(standard))
		{
			boolean deleteOk = ordre.getDelOrdre().remove(ordre.getDelOrdre().get(i));
			if (delOrdreId >= 0 && deleteOk) // if deleteok is true it will delete the Service
			{
				deleteList.add(delo);
				if (!delo.getEkstraServiceList().isEmpty())// not empty
				{
					for (EkstraService es : delo.getEkstraServiceList())
					{
						if (es.getEkstraServiceId() > -1)
						{
							deleteEkstraList.add(es);
						}
					}
				}
			}
		}
		else
		{
			if (!ordre.getDelOrdre().get(i).getEkstraServiceList().isEmpty())// ExtraserviceList is
																				// not empty
			{
				EkstraService es = getEkstraService(delOrdreId, standard);
				boolean deleteOk = ordre.getDelOrdre().get(i).getEkstraServiceList().remove(es);
				if (es.getEkstraServiceId() > -1 && deleteOk)
				{
					deleteEkstraList.add(es);
				}
			}
		}
	}

	public int getDelOrdreIndex(int delOrdreId)
	{
		int i = 0;
		boolean found = false;
		while (!found && i < ordre.getDelOrdre().size())
		{
			DelOrdre delo = ordre.getDelOrdre().get(i);
			if (delo.getDelordreId() == delOrdreId)
			{
				found = true;
			}
			else
			{
				i++;
			}
		}
		return i;
	}

	public EkstraService getEkstraService(int delOrdreId, String standard)
	{
		EkstraService tmpES = null;
		int index = getDelOrdreIndex(delOrdreId);
		int i = 0;
		boolean found = false;
		while (!found
				&& i < ordre.getDelOrdre().get(index).getEkstraServiceList()
						.size())
		{
			EkstraService es = ordre.getDelOrdre().get(index).getEkstraServiceList().get(i);
			if (es.getBeskrivelse().equals(standard))
			{
				tmpES = es;
				found = true;
			}
			else
			{
				i++;
			}
		}
		return tmpES;
	}

	@Override
	public void commitPaintingOrdre() throws Exception
	{
		// Check if the order is below 0
		if (ordre.getOrdreId() < 0)
		{
			ordre.setNote("");
			ordre.setOrdreType("Painting");
			OrdreCtr oCtr = new OrdreCtr();
			oCtr.createOrdre(ordre);
		}
		// It wasn't this means we are updating an existing order
		else
		{
			OrdreCtr oCtr = new OrdreCtr();
			oCtr.updateOrdre(ordre);
			DBDelOrdre dbDO = new DBDelOrdre();
			for (DelOrdre d : deleteList)
			{
				dbDO.deleteDelOrdre(d);
			}
			DBEkstraService dbES = new DBEkstraService();
			for (EkstraService es : deleteEkstraList)
			{
				dbES.deleteEkstraService(es);
			}
		}
	}

	public Ordre getOrdre()
	{
		return ordre;
	}

	public int useRunningId()
	{
		// subtract one from the current id, and return it.
		runningId = runningId - 1;
		return runningId;
	}

	// running id starts at 0, because when used it subtracts -1 before the id is returned.
	public void resetRunningId()
	{
		this.runningId = 0;
	}
}
